/*
 * @Author: lixu lixu@puchigames.com
 * @Date: 2025-07-03 16:49:48
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-09-19 17:33:22
 * @FilePath: /ix-utils/array.go
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
package ixUtils

// Contains 判断切片是否包含某元素
func Contains[T comparable](arr []T, v T) bool {
	for _, item := range arr {
		if item == v {
			return true
		}
	}
	return false
}

// IndexOf 返回元素首次出现的索引，未找到返回 -1
func IndexOf[T comparable](arr []T, v T) int {
	for i, item := range arr {
		if item == v {
			return i
		}
	}
	return -1
}

// Unique 去重，返回新切片
func Unique[T comparable](arr []T) []T {
	m := make(map[T]struct{})
	res := make([]T, 0, len(arr))
	for _, v := range arr {
		if _, ok := m[v]; !ok {
			m[v] = struct{}{}
			res = append(res, v)
		}
	}
	return res
}

// Filter 过滤，返回满足条件的新切片
func Filter[T any](arr []T, f func(T) bool) []T {
	res := make([]T, 0)
	for _, v := range arr {
		if f(v) {
			res = append(res, v)
		}
	}
	return res
}

// Map 映射，返回新切片
func Map[T any, R any](arr []T, f func(T) R) []R {
	res := make([]R, len(arr))
	for i, v := range arr {
		res[i] = f(v)
	}
	return res
}

// Any 判断是否有元素满足条件
func Any[T any](arr []T, f func(T) bool) bool {
	for _, v := range arr {
		if f(v) {
			return true
		}
	}
	return false
}

// All 判断是否所有元素都满足条件
func All[T any](arr []T, f func(T) bool) bool {
	for _, v := range arr {
		if !f(v) {
			return false
		}
	}
	return true
}

// Remove 移除所有等于 v 的元素，返回新切片
func Remove[T comparable](arr []T, v T) []T {
	res := make([]T, 0, len(arr))
	for _, item := range arr {
		if item != v {
			res = append(res, item)
		}
	}
	return res
}

// Reverse 反转切片，返回新切片
func Reverse[T any](arr []T) []T {
	res := make([]T, len(arr))
	for i, v := range arr {
		res[len(arr)-1-i] = v
	}
	return res
}

// Concat 合并多个切片，返回新切片
func Concat[T any](slices ...[]T) []T {
	var total int
	for _, s := range slices {
		total += len(s)
	}
	res := make([]T, 0, total)
	for _, s := range slices {
		res = append(res, s...)
	}
	return res
}

// Union 合并两个切片并去重，返回新切片
func Union[T comparable](a, b []T) []T {
	m := make(map[T]struct{})
	res := make([]T, 0, len(a)+len(b))
	for _, v := range a {
		if _, ok := m[v]; !ok {
			m[v] = struct{}{}
			res = append(res, v)
		}
	}
	for _, v := range b {
		if _, ok := m[v]; !ok {
			m[v] = struct{}{}
			res = append(res, v)
		}
	}
	return res
}

// Intersect 求两个切片的交集，返回新切片
func Intersect[T comparable](a, b []T) []T {
	m := make(map[T]struct{})
	for _, v := range b {
		m[v] = struct{}{}
	}
	res := make([]T, 0)
	for _, v := range a {
		if _, ok := m[v]; ok {
			res = append(res, v)
		}
	}
	return Unique(res)
}

// Difference 求 a 相对于 b 的差集（a 中有而 b 中没有的元素）
func Difference[T comparable](a, b []T) []T {
	m := make(map[T]struct{})
	for _, v := range b {
		m[v] = struct{}{}
	}
	res := make([]T, 0)
	for _, v := range a {
		if _, ok := m[v]; !ok {
			res = append(res, v)
		}
	}
	return res
}
